﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;

namespace Basic.Core.Application.Services;

[ApiController]
[Route("[controller]/[action]")]
public abstract class ApiApplicationService : IApplicationService
{
    private ControllerContext _controllerContext;
    private IModelMetadataProvider _metadataProvider;
    private IModelBinderFactory _modelBinderFactory;
    private IObjectModelValidator _objectValidator;
    private IUrlHelper _url;
    private ProblemDetailsFactory _problemDetailsFactory;

    public HttpContext HttpContext => this.ControllerContext.HttpContext;

    public HttpRequest Request => this.HttpContext?.Request;

    public HttpResponse Response => this.HttpContext?.Response;

    public RouteData RouteData => this.ControllerContext.RouteData;

    public ModelStateDictionary ModelState => this.ControllerContext.ModelState;

    public IServiceProvider ServiceProvider => this.HttpContext?.RequestServices;

    [ControllerContext]
    public ControllerContext ControllerContext
    {
        get => this._controllerContext ??= new ControllerContext();
        set => this._controllerContext = value != null ? value : throw new ArgumentNullException(nameof(value));
    }

    public IModelMetadataProvider MetadataProvider
    {
        get
        {
            if (this._metadataProvider == null)
            {
                HttpContext httpContext = this.HttpContext;
                IModelMetadataProvider metadataProvider;
                if (httpContext == null)
                {
                    metadataProvider = null;
                }
                else
                {
                    IServiceProvider requestServices = httpContext.RequestServices;
                    metadataProvider = requestServices?.GetRequiredService<IModelMetadataProvider>() ?? null;
                }
                this._metadataProvider = metadataProvider;
            }
            return this._metadataProvider;
        }
        set
        {
            this._metadataProvider = value != null ? value : throw new ArgumentNullException(nameof(value));
        }
    }

    public IModelBinderFactory ModelBinderFactory
    {
        get
        {
            if (this._modelBinderFactory == null)
            {
                HttpContext httpContext = this.HttpContext;
                IModelBinderFactory modelBinderFactory;
                if (httpContext == null)
                {
                    modelBinderFactory = null;
                }
                else
                {
                    IServiceProvider requestServices = httpContext.RequestServices;
                    modelBinderFactory = requestServices?.GetRequiredService<IModelBinderFactory>() ?? null;
                }
                this._modelBinderFactory = modelBinderFactory;
            }
            return this._modelBinderFactory;
        }
        set
        {
            this._modelBinderFactory = value != null ? value : throw new ArgumentNullException(nameof(value));
        }
    }

    public IUrlHelper Url
    {
        get
        {
            if (this._url == null)
            {
                HttpContext httpContext = this.HttpContext;
                IUrlHelperFactory urlHelperFactory;
                if (httpContext == null)
                {
                    urlHelperFactory = null;
                }
                else
                {
                    IServiceProvider requestServices = httpContext.RequestServices;
                    urlHelperFactory = requestServices?.GetRequiredService<IUrlHelperFactory>() ?? null;
                }
                this._url = urlHelperFactory?.GetUrlHelper((ActionContext)this.ControllerContext);
            }
            return this._url;
        }
        set => this._url = value != null ? value : throw new ArgumentNullException(nameof(value));
    }

    public IObjectModelValidator ObjectValidator
    {
        get
        {
            if (this._objectValidator == null)
            {
                HttpContext httpContext = this.HttpContext;
                IObjectModelValidator objectModelValidator;
                if (httpContext == null)
                {
                    objectModelValidator = null;
                }
                else
                {
                    IServiceProvider requestServices = httpContext.RequestServices;
                    objectModelValidator = requestServices?.GetRequiredService<IObjectModelValidator>() ?? null;
                }
                this._objectValidator = objectModelValidator;
            }
            return this._objectValidator;
        }
        set
        {
            this._objectValidator = value != null ? value : throw new ArgumentNullException(nameof(value));
        }
    }

    public ProblemDetailsFactory ProblemDetailsFactory
    {
        get
        {
            if (this._problemDetailsFactory == null)
            {
                HttpContext httpContext = this.HttpContext;
                ProblemDetailsFactory problemDetailsFactory;
                if (httpContext == null)
                {
                    problemDetailsFactory = null;
                }
                else
                {
                    IServiceProvider requestServices = httpContext.RequestServices;
                    problemDetailsFactory = requestServices?.GetRequiredService<ProblemDetailsFactory>() ?? null;
                }
                this._problemDetailsFactory = problemDetailsFactory;
            }
            return this._problemDetailsFactory;
        }
        set
        {
            this._problemDetailsFactory = value != null ? value : throw new ArgumentNullException(nameof(value));
        }
    }

}